/*
 * Copyright (c) 2010 Curtis Boyden.  All rights reserved. 
 * This software was developed by Curtis Boyden and is provided under the terms 
 * of the GNU Lesser General Public License, Version 2.1. You may not use 
 * this file except in compliance with the license. If you need a copy of the license, 
 * please go to http://www.gnu.org/licenses/lgpl-2.1.txt. The Original Code is ejMud
 * (Ewerp Java MUD).  The Initial Developer is Curtis Boyden.
 *
 * Software distributed under the GNU Lesser Public License is distributed on an "AS IS" 
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or  implied. Please refer to 
 * the license for the specific language governing your rights and limitations.
 */

package com.ewerp.mud.app;

import java.util.ArrayList;
import java.util.List;

import com.ewerp.server.plugins.EwerpPluginManager;
import com.ewerp.server.plugins.ILifecycleListener;
import com.ewerp.server.plugins.ILifecycleProvider;
import com.ewerp.server.plugins.IPluginManager;

public class EwerpMud implements ILifecycleProvider, ILifecycleListener, Runnable {
    private static final EwerpMud instance = new EwerpMud();

    public static final Object shutdown = new Object();

    protected IPluginManager pluginManager = null;
    protected final List<ILifecycleListener> lifecycleListeners = new ArrayList<ILifecycleListener>();

    protected enum LifecycleState {
        INIT, RUN, STOP
    };

    public static void main(String[] args) {
        try {
            EwerpMud.getInstance().setPluginManager(EwerpPluginManager.getInstance());
            EwerpMud.getInstance().registerListener(EwerpPluginManager.getInstance());
            
            EwerpMud.getInstance().run();
        } catch (Exception e) {
            // TODO: Improve
            e.printStackTrace();
        }
    }

    public static final EwerpMud getInstance() {
        return instance;
    }

    @Override
    public void run() {
        try {
            // Initialize plugins
            notifyLifecycle(LifecycleState.INIT);

            notifyLifecycle(LifecycleState.RUN);

            waitForShutdownSignal();

            notifyLifecycle(LifecycleState.STOP);

        } catch (Exception e) {
            // TODO: Improve
            e.printStackTrace();
        }
    }

    public void notifyShutdown() {
        synchronized (shutdown) {
            shutdown.notifyAll();
        }
    }

    @Override
    public void registerListener(ILifecycleListener listener) {
        lifecycleListeners.add(listener);
    }

    @Override
    public void unregisterListener(ILifecycleListener listener) {
        lifecycleListeners.remove(listener);
    }
    
    @Override
    public void init() {
        // Nothing to do
    }

    @Override
    public void start() {
        // Nothing to do
    }

    @Override
    public void stop() {
        notifyShutdown();
    }

    protected void waitForShutdownSignal() {
        synchronized (shutdown) {
            try {
                shutdown.wait();
            } catch (InterruptedException e) {
            }
        }
    }

    protected void setPluginManager(IPluginManager pluginManager) {
        this.pluginManager = pluginManager;
    }

    protected IPluginManager getPluginManager() {
        return pluginManager;
    }

    protected void notifyLifecycle(LifecycleState lifecycleState) {
        switch (lifecycleState) {
        case INIT: {
            for (ILifecycleListener listener : lifecycleListeners) {
                listener.init();
            }
        }
            break;
        case RUN: {
            for (ILifecycleListener listener : lifecycleListeners) {
                listener.start();
            }
        }
            break;
        case STOP: {
            for (ILifecycleListener listener : lifecycleListeners) {
                listener.stop();
            }
        }
            break;
        }
    }
}
